/*User program on Nachos
  For project 4
*/

/*Author: Yuzhe Wu 4/14*/

#include "create.h"

void main() {
	int mypatientERID = -1;
	int myNurseID = -1;
	int *tmpNurseID = NULL;
	int id = -1;
	bool debugFlag = true;
	int docRoomCounterValue = 0;
	int nurseIDFirstItemValue = 0;
	
	struct examSheet myLocalExamSheet;
	myMV docNum = -1;

	/*Printf("P4DEBUG: I am doctor, in!"\n);*/
	doCreate();
	
	rpcAcquireLock(doctorIndexLock);
	id=rpcGetValueMV(doctorIndex,0);
	rpcSetValueMV(doctorIndex,0,(id+1));
	rpcReleaseLock(doctorIndexLock);
	
	if(debugFlag == true) {
		Printf("myDEBUG: doctor [%d]: I entered!\n", id);
	}
	
	while(1){
		rpcAcquireLock(docStateLock);
		
		
		if((docRoomCounterValue=rpcGetValueMV(docRoomCounter,0)) > 0) { /*A nurse is in line*/
			/*Remove*/
			nurseIDFirstItemValue=rpcGetValueMV(nurseIDFirstItem,0);
			myNurseID = rpcGetValueMV(nurseIDList,nurseIDFirstItemValue);
			rpcSetValueMV(nurseIDFirstItem,0,nurseIDFirstItemValue+1);

			if(rpcGetValueMV(nurseIDFirstItem,0) == rpcGetValueMV(nurseIDListNum,0)) {
				rpcSetValueMV(nurseIDFirstItem,0,0);
			}
			if(myNurseID == -1) {
				Printf("DEBUG FATAL ERROR: doctor [%d] don't have nurse waiting.\n",id);	
			}
			
			rpcSetValueMV(docIDTONurse,myNurseID,id);
			rpcSetValueMV(nurseIDVerify,id,myNurseID);
			rpcSetValueMV(docRoomCounter,0,docRoomCounterValue-1);
			rpcSetValueMV(docState,id,BUSY);

			rpcSignalCV(docStateLock, nurseWaitingDocCV);
			
			if(debugFlag == true) {
				Printf("myDEBUG:doctor [%d] has waken up a nurse\n",id);
			}
			
			rpcWaitCV(docStateLock,nurseWaitingDocCV);
		}
		
		else{	/*No nurse is waiting, but which do not means the doctor should be idle*/
			rpcSetValueMV(docState,id,FREE);
		}
		
		rpcAcquireLock(docLock[id]);
		rpcReleaseLock(docStateLock);
		
		if(debugFlag == true) {
			Printf("myDEBUG: doctor [%d] is waiting for nurse\n", id);
		}
		
		rpcWaitCV(docLock[id],nurseDocCV[id]); /*Wait for nurse*/
		
		mypatientERID = rpcGetValueMV(examIDTODoctor,id);
		
		rpcSignalCV(docLock[id], nurseDocCV[id]);
		rpcReleaseLock(docLock[id]);	
		rpcAcquireLock(examRoomLock[mypatientERID]);
		
		if(debugFlag == true) {
			Printf("myDEBUG: Doctor [%d] is finish interact with nurse\n",id);
		}	
		Printf("Doctor [%d] is leaving their office.\n", id);
		
		/*Start interaction doctor & patient*/
		rpcSetValueMV(docIDTOPatient,mypatientERID,id);
		rpcAcquireLock(docLock[id]);
		rpcSignalCV(examRoomLock[mypatientERID],patientWaitingDocCV[mypatientERID]);
		rpcReleaseLock(examRoomLock[mypatientERID]);
		
		rpcWaitCV(docLock[id],docPatientCV[id]);
		
		rpcGetExamSheet(docExamSheet[id], &myLocalExamSheet);
		if(myLocalExamSheet.nextDestination == NOWHERE){
			Printf("Doctor [%d] is reading the examination sheet of [Adult/Child] Patient [%s%d] in Examination room [%d]\n",id,myLocalExamSheet.name,myLocalExamSheet.patientID,mypatientERID);
			if(Rand(4) == 0) {	/*25% need a shot*/
				myLocalExamSheet.needShot = true;
				rpcSetExamSheet(docExamSheet[id],myLocalExamSheet);
				Printf("Doctor [%d] notes down in the sheet that [Adult/Child] Patient [%s%d] needs to be given a shot in Examination room [%d]\n",id,myLocalExamSheet.name,myLocalExamSheet.patientID,mypatientERID);
			}
			else {
				myLocalExamSheet.needShot = false;
				rpcSetExamSheet(docExamSheet[id],myLocalExamSheet);
			}
			
			if(Rand(4) == 1) {
				myLocalExamSheet.needXray = true;
				myLocalExamSheet.imageNum = Rand(3) + 1;
				rpcSetExamSheet(docExamSheet[id],myLocalExamSheet);				
				Printf("Doctor [%d] notes down in the sheet that Xray is needed for [Adult/Child] Patient [%s%d] in Examination room [%d]\n",id,myLocalExamSheet.name,myLocalExamSheet.patientID,mypatientERID);
				
			}
			else{
				myLocalExamSheet.needXray = false;
				rpcSetExamSheet(docExamSheet[id],myLocalExamSheet);				
			}
			
			rpcGetExamSheet(docExamSheet[id], &myLocalExamSheet);
			if((myLocalExamSheet.needShot == false) && (myLocalExamSheet.needXray == false)) {
				Printf("Doctor [%d] diagnoses [Adult/Child] Patient [%s%d] to be fine and is leaving Examination Room [%d]\n",id,myLocalExamSheet.name,myLocalExamSheet.patientID,mypatientERID);
			}
			
			if(myLocalExamSheet.needShot == true){
				myLocalExamSheet.nextDestination = EXAMROOM;
				rpcSetExamSheet(docExamSheet[id],myLocalExamSheet);	
			}
			else if(myLocalExamSheet.needXray == true){
				myLocalExamSheet.nextDestination = XRAYROOM;
				rpcSetExamSheet(docExamSheet[id],myLocalExamSheet);	
			}
			else{
				myLocalExamSheet.nextDestination = CASHIER; 
				rpcSetExamSheet(docExamSheet[id],myLocalExamSheet);	
			}
			
			if(debugFlag == true) {
				Printf("myDEBUG: Doctor [%d] FIRST interact [Adult/Child] Patient [%s%d] is leaving Examination Room [%d]\n",id,myLocalExamSheet.name,myLocalExamSheet.patientID,mypatientERID);
			}
			
			rpcSignalCV(docLock[id],docPatientCV[id]);
			rpcWaitCV(docLock[id],docPatientCV[id]);
			
			if(debugFlag == true) {
				Printf("myDEBUG DEBUG: Doctor [%d] FIRST interact [Adult/Child] Patient [%s%d] is leaving Examination Room [%d]\n",id,myLocalExamSheet.name,myLocalExamSheet.patientID,mypatientERID);
			}
		}
		
		else{
			if(debugFlag == true) {
				Printf("myDEBUG DEBUG: Doctor [%d] SECOND interact [Adult/Child] Patient [%s%d] is leaving Examination Room [%d]\n",id,myLocalExamSheet.name,myLocalExamSheet.patientID,mypatientERID);
			}
			Printf("Doctor [%d] is examining the Xrays of Adult Patient [%d] in Examination room [%d].\n", id, myLocalExamSheet.patientID, mypatientERID);
			/*print for parent*/
			Printf("Doctor [%d] has left Examination Room [%d].\n", id, mypatientERID);
			
			myLocalExamSheet.nextDestination = CASHIER; 
			rpcSetExamSheet(docExamSheet[id],myLocalExamSheet);	
		}
		
		rpcAcquireLock(examRoomLock[mypatientERID]);
		
		rpcGetExamSheet(docExamSheet[id], &myLocalExamSheet);	/*Post the examSheet in the Wall pocket*/
		rpcSetExamSheet(wallPocketER[mypatientERID],myLocalExamSheet);
		rpcSetStatus(wallPocketER[mypatientERID],USED);
	/*
		if(debugFlag == true) {
			Printf("myDEBUG: doctor[%d] put the exam sheet with name %s%d in wall pocket exam room\n", id, wallPocketER[mypatientERID]->name,wallPocketER[mypatientERID]->patientID);
		}
		
		if(wallPocketER[mypatientERID]->needXray == false){
			if(debugFlag == true) {
				Printf("myDEBUG:YOU DON'T NEED XRAY!\n");
			}	
		}
		else {
			if(debugFlag == true) {
				Printf("myDEBUG:YOU NEEEEEEED XRAY!!!!!!\n");
			}	
		}
		
		if(debugFlag == true) {
			Printf("myDEBUG:Doctor wallPocketER nextDEstination %d \n", wallPocketER[mypatientERID]->nextDestination);
		}
		
	*/
		rpcReleaseLock(examRoomLock[mypatientERID]);
		if(debugFlag == true) {
			Printf("myDEBUG: doctor [%d] post the ES\n",id);
		}
		
		rpcReleaseLock(docLock[id]);
		Printf("Doctor [%d] is going to their office.\n", id);
		
	/*	rpcAcquireLock(patientLeftNumLock);	
		if(rpcGetValueMV(patientLeftNum,0) == rpcGetValueMV(patientNum,0)) {
			Exit(0);
		}
		rpcReleaseLock(patientLeftNumLock);
	*/
	}
}